jQuery(document).ready(function(){
	jQuery("#tabs").tabs();
	
	jQuery('#colorpickerHolder').ColorPicker({flat: true});
	
	createUploader();
	
	inicializa();
	
});

//canvas
var gCanvas = null;
var gCtx = null;

// algumas configs
var w = 600;
var h = 400;

var pontos = new Array();
var pontosederivadas = new Array();
var mouseX = 0;
var mouseY = 0;

var canvasPos;
var quadradinho = 6;
var quadradinhoMeio = quadradinho/2; //para nao precisar gastar ciclos do cpu varias vezes com a mesma conta
var segmentoQuantidade = 100; // quantidade de segmentos
var formato = "";
var corLinha = "#000"; // preto
var recursao, continua;

var carregandoHermit = false;

function inicializa() {
	// capturando os valores nos inputs e renderizando o resultado
	jQuery("#submit").click(function(e){
		e.preventDefault(); // para evitar o comportamento natural do botao...
		
		segmentoQuantidade = parseInt(jQuery("#segmentos").attr('value'));
		corLinha = jQuery(".colorpicker_hex input").attr('value');
		formato = jQuery('.radio:checked').attr('value');
		if ((((pontos.length-1)%3 != 0) || (pontos.length < 4)) && !carregandoHermit)
			return alert('adicione pontos!')
		else
			return spline();
	});
	
	jQuery(".salvarPNG").click(function(e){
		e.preventDefault();
		salvar();
	});
	jQuery(".salvarJPG").click(function(e){
		e.preventDefault();
		salvar('jpg');
	});
	
	configCanvas();
	jQuery("#limpar").click(function(e){
		e.preventDefault();
		configCanvas();
		pontos = new Array();
		pontosederivadas = new Array();
	});
}

// atraves dos clicks mapeados, gera o spline
function spline() {
	if (formato == "Hermit") {
		hermitCubica(pontosederivadas, false);
	} else if (formato == "Bezier") {
		bezierCubica(pontos, false);
	}
	carregandoHermit = false;
	pontos = new Array();
	pontosederivadas = new Array();
}

// bezier de 3 ou 4 pontos
function bezierCubica(pontosTela, recursivo, xAux, yAux) {

	var pontosTemp;
	recursao = recursivo;

	pontosTemp = [pontosTela[0], pontosTela[1], pontosTela[2], pontosTela[3]];
		
	if (pontosTela.length > 4) { //temos q continuar a curva?
		var pontosConcat = pontosTela;
		for (var i = 0; i < 3; i++) { // removendo os 3 primeiros elementos
			pontosConcat.shift(); 
		}
		continua = true;
	} else {
		continua = false;
	}

	// Por enquanto soh estamos pegando os 4 primeiros pontos
	var p1x = pontosTemp[0].x;
	var p1y = pontosTemp[0].y;

	var p2x = pontosTemp[1].x;
	var p2y = pontosTemp[1].y;

	var p3x = pontosTemp[2].x;
	var p3y = pontosTemp[2].y;
	
	var p4x = pontosTemp[3].x; 
	var p4y = pontosTemp[3].y;

	var x = 0;
	var y = 0;
	
	var t = 0; // eh o parametro parametrico
	var tMax = 1; // t maximo
	
	gCtx.strokeStyle = corLinha; // cor do segmento (preto)
	
	var pontosCurva = new Array(); // pontos da curva a ser desenhada

	for(var i = 0; i < segmentoQuantidade; i++) {
		if(!recursao) {
			x = (1-t)*(1-t)*(1-t)* p1x + 3*(1-t)*(1-t)*t* p2x + 3*(1-t)*t*t* p3x + t*t*t* p4x; //bezier/casteljau para o ponto x
			y = (1-t)*(1-t)*(1-t)* p1y + 3*(1-t)*(1-t)*t* p2y + 3*(1-t)*t*t* p3y + t*t*t* p4y; // bezie/casteljaur para o ponto y
		} else {
			x = (1-t)*(1-t)*(1-t)*(1-t)*p1x + 4*(1-t)*(1-t)*(1-t)*t*xAux + 6*(1-t)*(1-t)*t*t*p2x + 4*(1-t)*t*t*t*p3x + t*t*t*t*p4x; //bezier/casteljau para o ponto x
			y = (1-t)*(1-t)*(1-t)*(1-t)*p1y + 4*(1-t)*(1-t)*(1-t)*t*yAux + 6*(1-t)*(1-t)*t*t*p2y + 4*(1-t)*t*t*t*p3y + t*t*t*t*p4y; //bezier/casteljau para o ponto x
		}

 		x = Math.round(x) + quadradinhoMeio; //como nao ha 1/2 pixel, arredondo!
		y = Math.round(y) + quadradinhoMeio; // esse +quadradinhoMeio magico eh para as linhas passarem pelo centro do quadradinho

		pontosCurva[pontosCurva.length] = new Ponto(x,y);  
		t = i/(segmentoQuantidade-1);		// para varia conforme numeros de segmentos
	}
	
	for (var i = 0; i < pontosCurva.length; i++) {
		x = pontosCurva[i].x;
		y = pontosCurva[i].y;
		if (i+1 != pontosCurva.length) { // para nao dar overflow
			proximoX = pontosCurva[i+1].x;
			proximoY = pontosCurva[i+1].y;
		}		
		gCtx.moveTo(x,y); // posiciona o lapis
		gCtx.lineTo(proximoX, proximoY); // e traca a linha				
	}
	
	gCtx.moveTo(x,y); // penultimo ponto
	gCtx.lineTo(p4x + quadradinhoMeio, p4y + quadradinhoMeio); // anda com o lapis ate o ponto final tracando a linha
	gCtx.stroke(); // desenha todas as linhas (lineTo() apenas joga no buffer as linhas, stroke() q desenha o q foi armazenado no buffer)

	if (continua) {
		var xAuxiliar = 2*p4x - p3x; // achando a velocidade (2a derivada)
		var yAuxiliar = 2*p4y - p3y;
		bezierCubica(pontosConcat, true, xAuxiliar, yAuxiliar);
	}
}
    
function hermitCubica(pontosTela, recursivo, xAux, yAux) {
	var pontosTemp;
	recursao = recursivo;

	pontosTemp = [pontosTela[0], pontosTela[1]];
		
	if (pontosTela.length > 2) { //temos q continuar a curva?
		var pontosConcat = pontosTela;
		pontosConcat.shift(); 
		continua = true; //removendo 1 ponto
	} else {
		continua = false;
	}

	// Por enquanto soh estamos pegando os 4 primeiros pontos
	var p1x = pontosTemp[0].x;
	var p1y = pontosTemp[0].y;
	
	if(pontos.length > 0) {
		
	}
	var p1x_linha = pontosTemp[0].x_linha;
	var p1y_linha = pontosTemp[0].y_linha;


	var p2x = pontosTemp[1].x;
	var p2y = pontosTemp[1].y;

	var p2x_linha = pontosTemp[1].x_linha;
	var p2y_linha = pontosTemp[1].y_linha;

	var x = 0;
	var y = 0;
	
	var t = 0; // eh o parametro parametrico
	var tMax = 1; // t maximo
	
	gCtx.strokeStyle = corLinha; // cor do segmento (preto)
	
	var pontosCurva = new Array(); // pontos da curva a ser desenhada

	for(var i = 0; i < segmentoQuantidade; i++) {
		x = (2*t*t*t - 3*t*t + 1)*p1x + (t*t*t - 2*t*t + t)*p1x_linha + (-2*t*t*t + 3*t*t)*p2x + (t*t*t - t*t)*p2x_linha;
		y = (2*t*t*t - 3*t*t + 1)*p1y + (t*t*t - 2*t*t + t)*p1y_linha + (-2*t*t*t + 3*t*t)*p2y + (t*t*t - t*t)*p2y_linha;

 		x = Math.round(x) + quadradinhoMeio; //como nao ha 1/2 pixel, arredondo!
		y = Math.round(y) + quadradinhoMeio; // esse +quadradinhoMeio magico eh para as linhas passarem pelo centro do quadradinho

		pontosCurva[pontosCurva.length] = new Ponto(x,y);  
		t = i/(segmentoQuantidade-1);		// para varia conforme numeros de segmentos
	}
	
	for (var i = 0; i < pontosCurva.length; i++) {
		x = pontosCurva[i].x;
		y = pontosCurva[i].y;
		if (i+1 != pontosCurva.length) { // para nao dar overflow
			proximoX = pontosCurva[i+1].x;
			proximoY = pontosCurva[i+1].y;
		}		
		gCtx.moveTo(x,y); // posiciona o lapis
		gCtx.lineTo(proximoX, proximoY); // e traca a linha				
	}
	
	gCtx.moveTo(x,y); // penultimo ponto
	gCtx.lineTo(p2x + quadradinhoMeio, p2y + quadradinhoMeio); // anda com o lapis ate o ponto final tracando a linha
	gCtx.stroke(); // desenha todas as linhas (lineTo() apenas joga no buffer as linhas, stroke() q desenha o q foi armazenado no buffer)

	if (continua) {
		hermitCubica(pontosConcat, true);	
	}
}


function configCanvas() {  
	// burocracia para configuracao do canvas
	gCanvas = document.getElementById("canvas");
	gCanvas.style.width = w + "px";
    gCanvas.style.height = h + "px";
    gCanvas.width = w; // tamanho do canvas
    gCanvas.height = h; // 
	gCtx = gCanvas.getContext("2d");
    gCtx.clearRect(0, 0, w, h);

	canvasPos = jQuery("#canvas").offset();
	
	// preparar para receber clicks	
	gCanvas.onmousemove = mouseXY;
	gCanvas.onclick = desenhaPonto;
	gCtx.save();
}



// ---------------- UTILS ----------------

// desenhando o ponto na tela, no futuro podemos deixar o usuario selecionar a cor 
function desenhaPonto() {
	gCtx.fillStyle = '#00f'; // azul
	pontos[pontos.length] = new Ponto(mouseX - quadradinhoMeio, mouseY - quadradinhoMeio);
	
	if (pontosederivadas.length == 0) {
		pontosederivadas[0] = new PontoEDerivada(mouseX, mouseY, -9999, -9999);
	} else if (pontosederivadas[pontosederivadas.length-1].x_linha == -9999 ) {
		pontosederivadas[pontosederivadas.length-1].x_linha = mouseX;
		pontosederivadas[pontosederivadas.length-1].y_linha = mouseY;
	} else {
		pontosederivadas[pontosederivadas.length] = new PontoEDerivada(mouseX, mouseY, -9999, -9999);
	}
    gCtx.fillRect(mouseX - quadradinhoMeio, mouseY - quadradinhoMeio, quadradinho, quadradinho);
	//gCtx.arc(mouseX-1, mouseY-1, 4, 0, Math.PI*2, true);   //Ta bugado no Firefox...
	//gCtx.fill();
}

// pega posicao do mouse no canvas
function mouseXY(e) {
	mouseX = e.pageX;
	mouseY = e.pageY;    

	if (mouseX < 0)
	mouseX = 0;
	if (mouseY < 0) 
	mouseY = 0;

	mouseX = parseInt(mouseX - canvasPos.left);
	mouseY = parseInt(mouseY - canvasPos.top);

	jQuery("#posX").text(mouseX);
	jQuery("#posY").text(mouseY);

	return true;
}

// usada para salvar como imagem
function salvar(extensao) {
	if (extensao) {
	  extensao = extensao.toLowerCase();
	}

	if (!extensao || (extensao !== 'png' && extensao !== 'jpg')) {
	  extensao = 'png';
	}

	document.location.href = toBase64(extensao).replace("image/" + extensao, "image/octet-stream");
}

// facilitanto a manipulacao da posicao (x,y) dos pontos... senao teriamos que usar arrays multimensionais classicos,
function Ponto(x,y) {
	this.x = 0;
	this.y = 0;
	

	if (arguments.length == 2) {
		this.x = x;
		this.y = y;
	}
}

function PontoEDerivada(x, y, x_linha, y_linha) {
	this.x = 0;
	this.y = 0;
	this.x_linha = 0;
	this.y_linha = 0;
	

	if (arguments.length == 4) {
		this.x = x;
		this.y = y;
		this.x_linha = x_linha;
		this.y_linha = y_linha;
	}
}
// usado na funcao anterior... necessario para o browser interpretar como 'imagem' 
function toBase64(extensao) {
	if (extensao) {
	  extensao = extensao.toLowerCase();
	}

	if (!extensao || (extensao !== 'png' && extensao !== 'jpg')) {
	  extensao = 'png';
	}

	return gCanvas.toDataURL("image/" + extensao);
}

function loadXML(arquivo) {
	var destino = 'ajaxupload/server/uploads/' + arquivo;
	jQuery.ajax({
		url: destino,
		dataType: "text xml",
		success: function(data) {
			segmentoQuantidade = jQuery(data).find("curva").attr('resolucao');
			jQuery("#segmentos").attr('value', segmentoQuantidade);
			canvasPos = jQuery("#canvas").offset();
			formato = jQuery(data).find("curva").attr('formato');
			if (formato == "Bezier") {
				jQuery(data).find("ponto").each(function(i){
					var ptoX = parseInt(jQuery(this).find("x").text());
					var ptoY = parseInt(jQuery(this).find("y").text());
					pontos[i] = new Ponto(ptoX, ptoY);
				});
				viewportBezier();
			}
			else if (formato == "Hermit") {
				carregandoHermit = true;
				jQuery(".radio:eq(1)").attr('checked', true);
				jQuery(data).find("ponto").each(function(i){
					var ptoX = parseInt(jQuery(this).find("> x").text());
					var ptoY = parseInt(jQuery(this).find("> y").text());
					var tangente = jQuery(this).find("> tangente");
					var x_linha = parseInt(jQuery(tangente).find("> x").text());
					var y_linha = parseInt(jQuery(tangente).find("> y").text());
					pontosederivadas[i] = new PontoEDerivada(ptoX, ptoY, x_linha, y_linha);
				});
				viewportHermit();
			}
		}
	});
}

function plotandoPontos(pontoX, pontoY) {
	gCtx.fillStyle = '#00f';
	gCtx.fillRect(pontoX, pontoY, quadradinho, quadradinho);
}

function viewportHermit() {
	var max_X = 0;
	var	max_Y = 0;
	var fator;
	for (var i = 0; i < pontosederivadas.length; i++) {
		if (pontosederivadas[i].x > max_X)
			max_X = pontosederivadas[i].x;
		if (pontosederivadas[i].y > max_Y)
			max_Y = pontosederivadas[i].y;
		if (pontosederivadas[i].x_linha > max_X)
			max_X = pontosederivadas[i].x_linha;
		if (pontosederivadas[i].y_linha > max_Y)
			max_Y = pontosederivadas[i].y_linha;
	}
	if (max_X > w) {
		fator = w / max_X;
		for (var i = 0; i < pontosederivadas.length; i++) {
			pontosederivadas[i].x = Math.round(pontosederivadas[i].x * fator) - quadradinho;
			pontosederivadas[i].x_linha = Math.round(pontosederivadas[i].x_linha * fator) - quadradinho;
		}
	}
	if (max_Y > h) {
		fator = h / max_Y;
		for (var i = 0; i < pontosederivadas.length; i++) {
			pontosederivadas[i].y = Math.round(pontosederivadas[i].y * fator) - quadradinho;
			pontosederivadas[i].y_linha = Math.round(pontosederivadas[i].y_linha * fator) - quadradinho;
		}
	}
	for (var i = 0; i < pontosederivadas.length; i++) {
		plotandoPontos(pontosederivadas[i].x, pontosederivadas[i].y);		
		plotandoPontos(pontosederivadas[i].x_linha, pontosederivadas[i].y_linha);
	}
}

function viewportBezier() {
	var max_X = 0;
	var	max_Y = 0;
	var fator;
	for (var i = 0; i < pontos.length; i++) {
		if (pontos[i].x > max_X)
			max_X = pontos[i].x;
		if (pontos[i].y > max_Y)
			max_Y = pontos[i].y;
	}
	if (max_X > w) {
		fator = w / max_X;
		for (var i = 0; i < pontos.length; i++) {
			pontos[i].x = Math.round(pontos[i].x * fator) - quadradinho;
		}
	}
	if (max_Y > h) {
		fator = h / max_Y;
		for (var i = 0; i < pontos.length; i++) {
			pontos[i].y = Math.round(pontos[i].y * fator) - quadradinho;
		}
	}
	for (var i = 0; i < pontos.length; i++) {
		plotandoPontos(pontos[i].x, pontos[i].y);
	}
}

 function createUploader(){            
	var uploader = new qq.FileUploader({
		element: document.getElementById('xmlUpload'),
		action: 'ajaxupload/server/upload.php',
		onComplete: function(id, response) {
			loadXML(response);
		}
	});           
}
